<?php
// +----------------------------------------------------------------------
// | INPHP
// | Copyright (c) 2023 https://inphp.cc All rights reserved.
// | Licensed ( https://opensource.org/licenses/MIT )
// | Author: 幺月儿(https://gitee.com/lulanyin) Email: inphp@qq.com
// +----------------------------------------------------------------------
// | 文件管理
// +----------------------------------------------------------------------
namespace app\fs\http\api;

use app\admin\attributes\auth;
use app\fs\model\FilesModel;
use Inphp\Core\Config;
use Inphp\Core\Db\Redis;
use Inphp\Core\Object\Message;
use Inphp\Core\Util\Str;

#[auth] class files
{
    /**
     * UID
     * @var int
     */
    public int $uid = 0;

    /**
     * 账号数据
     * @var array
     */
    public array $user = [];

    /**
     * 获取文件列表
     * @return array
     */
    public function list(): array
    {
        //数据库查询构建
        $db = FilesModel::emptyQuery();
        //文件类型筛选：文件夹、图片、视频、其它文件
        $type = GET("type");
        $type = !empty($type) ? Str::trim($type) : null;
        if (!empty($type) && strtolower($type) != "all") {
            $db->whereIn("type", [$type, "dir"]);
        }
        //上级文件夹ID
        $parentId = GET("parentId", 0);
        $parentId = is_numeric($parentId) && $parentId > 0 ? ceil($parentId) : 0;
        $db->where("parentId", $parentId);
        //分组
        $groupName = GET("groupName");
        if (!empty($groupName) || $groupName == "0") {
            $db->where("groupName", (string) $groupName);
        }
        //搜索
        $keyword = GET("keyword");
        $keyword = !empty($keyword) ? trim($keyword) : null;
        if (!empty($keyword)) {
            $db->whereLike("name", $keyword);
        }
        //取全部
        $list = $db->where("destroy", 0)->orderBy("weight", "asc")->orderBy("name", "asc")->get();
        foreach ($list as &$item) {
            $item["url"] = !empty($item["src"]) ? attachmentUrl($item["src"]) : null;
        }
        return $list;
    }

    /**
     * 获取所有父级
     * @param int $id
     * @return array
     */
    public function parents(int $id = 0): array
    {
        $id = $id > 0 ? $id : GET("id");
        $id = is_numeric($id) && $id > 0 ? ceil($id) : 0;
        if($id <= 0)
        {
            return [];
        }
        $item = FilesModel::emptyQuery()
            ->where("id", $id)
            ->where("type", 'dir')
            ->where("destroy", 0)
            ->first();
        if (empty($item)) {
            return [];
        }
        if ($item["parentId"] > 0) {
            $parents = $this->parents($item["parentId"]);
            return !empty($parents) ? array_merge($parents, [$item]) : [$item];
        } else {
            return [$item];
        }
    }

    /**
     * 删除文件
     * @return Message
     */
    public function delete(): Message
    {
        $idList = POST("id");
        //处理
        $idList = !empty($idList) ? explode(",", Str::trim($idList)) : [];
        if (empty($idList)) {
            return httpMessage("未指定文件的ID");
        }
        $id = [];
        foreach ($idList as $val) {
            if (is_numeric($val) && $val > 0 && !in_array($val, $id)) {
                $id[] = $val;
            }
        }
        if (empty($id)) {
            return httpMessage("未指定文件的ID，数据无效！");
        }
        $db = FilesModel::emptyQuery()
            ->whereIn("id", $id);
        if ($this->user["admin"] != 1) {
            $db->where("uid", $this->uid);
        }
        if ($db->update(["destroy" => 1])) {
            return httpMessage(0, "作废了{$db->getAffectRows()}个文件");
        }
        return httpMessage("文件作废失败");
    }

    /**
     * 保存文件
     * @return Message
     */
    public function save(): Message
    {
        $id = POST("id");
        $id = is_numeric($id) && $id > 0 ? ceil($id) : 0;
        $name = POST("name");
        $name = !empty($name) ? trim(Str::trim($name, " ")) : null;
        if (empty($name)) {
            return httpMessage("缺少名称");
        }
        if (mb_strlen($name) > 100) {
            $name = mb_substr($name, 0, 100);
        }
        if ($id > 0) {
            //修改
            $db = FilesModel::emptyQuery()->where("id", $id)->set("name", $name);
            if ($this->user["admin"] != 1) {
                $db->where("uid", $this->uid);
            }
            if ($db->update()) {
                return httpMessage(0, "修改成功");
            }
            return httpMessage("修改失败，请稍后再试");
        } else {
            //创建文件夹
            //父级ID
            $parentId = POST("parentId", 0);
            $parentId = is_numeric($parentId) && $parentId > 0 ? ceil($parentId) : 0;
            //分组名称
            $groupName = POST("groupName");
            $groupName = !empty($groupName) ? Str::trim($groupName) : "other";
            $groupName = !empty($groupName) ? $groupName : "other";
            //查询是否有重名文件夹
            $exists = FilesModel::emptyQuery()
                ->where("parentId", $parentId)
                ->where("groupName", $groupName)
                ->where("name", $name)
                ->where("type", 'dir')
                ->where("destroy", 0)
                ->first();
            if (!empty($exists)) {
                return httpMessage("已存在相同文件夹名称！");
            }
            //保存
            $data = [
                "parentID"      => $parentId,
                "groupName"     => $groupName,
                "name"          => $name,
                "hash"          => "dir",
                "type"          => "dir",
                "ip"            => getIP(),
                //文件夹永远排第一
                "weight"        => 1,
                "uid"           => $this->uid
            ];
            $db = FilesModel::emptyQuery();
            if ($db->insert($data)) {
                return httpMessage(0, "创建文件夹成功。");
            }
            return httpMessage("创建文件夹失败，请稍后再试！");
        }
    }

    /**
     * MD5检测
     * @return Message
     */
    public function exists(): Message
    {
        $hash = POST("hash");
        $hash = !empty($hash) ? Str::trim($hash) : null;
        if (empty($hash) || strlen($hash) !== 32) {
            return httpMessage("缺少MD5值");
        }
        //父级ID
        $parentId = POST("parentId", 0);
        $parentId = is_numeric($parentId) && $parentId > 0 ? ceil($parentId) : 0;
        //分组名称
        $groupName = POST("groupName");
        $groupName = !empty($groupName) ? Str::trim($groupName) : "other";
        $groupName = !empty($groupName) ? $groupName : "other";
        //文件名称
        $name = POST("name");
        $name = !empty($name) ? trim(Str::trim($name, "")) : "";
        if (mb_strlen($name) > 100) {
            $name = mb_substr($name, 0, 100);
        }
        //检测同文件夹下，是否存在同样的文件
        $exists = FilesModel::emptyQuery()
            ->where("type", "!=", "dir")
            ->where("hash", $hash)
            ->where("parentId", $parentId)
            ->where("groupName", $groupName)
            ->first();
        if (empty($exists)) {
            //如果不存在，再使用hash检查
            $exists = FilesModel::emptyQuery()
                ->where("type", "!=", "dir")
                ->where("hash", $hash)
                ->first();
            if (empty($exists)) {
                return httpMessage("不存相同文件");
            }
            //保存一份到当前文件夹
            $copy = [
                "parentId"  => $parentId,
                "groupName" => $groupName,
                "name"      => !empty($name) ? $name : $exists["name"],
                "extension" => $exists["extension"],
                "src"       => $exists["src"],
                "hash"      => $exists["hash"],
                "ip"        => getIP(),
                "type"      => $exists["type"],
                "uid"       => $this->uid,
                "size"      => $exists["size"]
            ];
            $db = FilesModel::emptyQuery()->set($copy);
            if ($db->insert()) {
                $exists["id"] = $db->getLastInsertId();
                $exists["destroy"] = 0;
            }
        }
        if ($exists["destroy"] == 1) {
            //恢复文件
            FilesModel::emptyQuery()->where("id", $exists["id"])->update(["destroy" => 0]);
        }
        //如果不属于同一个
        //处理
        $exists["url"] = attachmentUrl($exists["src"]);
        //返回数据
        return httpMessage($exists);
    }

    /**
     * 解压文件
     * @return Message
     */
    public function unzip(): Message
    {
        $id = POST("id");
        $id = is_numeric($id) && $id > 0 ? ceil($id) : 0;
        if ($id <= 0) {
            return httpMessage("文件ID无效");
        }
        //查询解压状态
        $state = Redis::get("fs_unzip_{$id}");
        if ($state == 2) {
            return httpMessage(0, "文件正在解压");
        }
        $file = FilesModel::emptyQuery()->where("id", $id)->first();
        if (empty($file)) {
            return httpMessage("文件不存在");
        }
        if ($file["extension"] !== "zip") {
            return httpMessage("非ZIP文件，无法解压");
        }
        $attachment = Config::get("define.attachment");
        $src = $attachment.$file["src"];
        if (!is_file($src)) {
            return httpMessage("文件已丢失，无法解压");
        }
        //开始解压
        //$cmd = "php ".ROOT."/bin/cmd app.fs.cmd.unzip id={$id} > /dev/null 2>&1 &";
        CMD_RUN("app.fs.cmd.unzip", [
            "id"    => $id
        ]);
        //@exec($cmd, $output, $code);
        return httpMessage(0, "解压命令已执行");
    }

    /**
     * 解压状态查看
     * @return Message
     */
    public function unzipState(): Message
    {
        $id = GET("id");
        $id = is_numeric($id) && $id > 0 ? ceil($id) : 0;
        if ($id <= 0) {
            return httpMessage("文件ID无效");
        }
        $state = Redis::get("fs_unzip_{$id}");
        return httpMessage([
            "state"     => $state ?? 0
        ]);
    }
}